﻿using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TimberSmart.Data.Contracts;
using TimberSmart.Data.Repositories;
using TimberSmart.Model;
using TimberSmart.Model.Security;
using TimberSmart.Model.Common;
using TimberSmart.Model.Business;

namespace TimberSmart.Data
{
    // Unit of work pattern. http://dotnet.dzone.com/news/using-unit-work-pattern-entity
    public class TimberSmartUow : ITimberSmartUow
    {
        private DbContext _dbContext { get; set; }
        private RepositoryProvider _repositoryProvider;
        private Dictionary<Type, object> _repositories;

        // Repositories for this UoW.
        public IUserRepository UserRepository { get { return GetRepository<IUserRepository>(); } }

        // Automatically pass in our RepositoryFactoryCollection, You can also pass it in with mock factories.
        public TimberSmartUow() : this(RepositoryFactoryCollection.DefaultInstance) { }

        public TimberSmartUow(RepositoryFactoryCollection factories)
        {
            _repositoryProvider = new RepositoryProvider(factories);
            _repositories = new Dictionary<Type, object>();
            _dbContext = new TimberSmartDbContext();
        }

        // Get a custom I[Something]Repository. Make sure it's in RepositoryFactories.
        private T GetRepository<T>() where T : class
        {
            if (!_repositories.ContainsKey(typeof(T)))
            {
                var repository = (T)this._repositoryProvider
                    .GetRepositoryFactory<T>()(this._dbContext);


                _repositories.Add(typeof(T), repository);
            }

            return (T)_repositories[typeof(T)];
        }

        // Save data.
        public void Commit()
        {            
            
            this._dbContext.SaveChanges();
            // May throw DbUpdateConcurrencyException
        }

        // Finished with UoW.
        public void Dispose()
        {
            this._dbContext.Dispose();
        }
    }
}
